﻿/*
* This software is licensed under the GNU General Public License, version 2
* You may copy, distribute and modify the software as long as you track changes/dates of in source files and keep all modifications under GPL. You can distribute your application using a GPL library commercially, but you must also provide the source code.

* DNNspot Software (http://www.dnnspot.com)
* Copyright (C) 2013 Atriage Software LLC
* Authors: Kevin Southworth, Matthew Hall, Ryan Doom

* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.

* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.

* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

* Full license viewable here: http://www.gnu.org/licenses/gpl-2.0.txt
*/

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
using DotNetNuke.Common;
using DotNetNuke.Entities.Host;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Modules.Actions;
using DotNetNuke.Security;
using DNNspot.Tabs.Common;
using DNNspot.Tabs.DataModel;

namespace DNNspot.Tabs
{
    public partial class Default : ModuleBase, IActionable
    {
        #region Members

        private String _style;
        private int? _templateId = null;

        #endregion

        #region Properties

        public ModuleActionCollection ModuleActions
        {
            get
            {
                var actions = new ModuleActionCollection();

                actions.Add(
                    GetNextActionID(),
                    "Edit Panes",
                    ModuleActionType.AddContent,
                    "",
                    "",
                    EditUrl(ControlKeys.ListPanes),
                    false,
                    SecurityAccessLevel.Edit,
                    true,
                    false);


                //actions.Add(
                //    GetNextActionID(),
                //    "Edit Templates",
                //    ModuleActionType.AddContent,
                //    "",
                //    "",
                //    EditUrl(ControlKeys.Templates),
                //    false,
                //    SecurityAccessLevel.Edit,
                //    true,
                //    false);

                return actions;
            }
        }

        #endregion

        #region Events

        protected void Page_Load(object sender, EventArgs e)
        {

            if (!IsPostBack)
            {
                LoadVariables();
                GenerateDOM();
                GenerateJavascript();
            }
        }

        protected void Page_PreRender(object sender, EventArgs e)
        {
            IncludeJS();
        }

        #endregion

        #region Functions

        private void GenerateJavascript()
        {
            var jsString = new StringBuilder();

            jsString.Append("jQuery(function() { ");
            jsString.Append(string.Format("jQuery(\"ul#Tabs_{0}_tabs\").dnnspotTabs(\"div#Tabs_{0}_panes > div.Tabs_{0}_pane\"", ModuleId));
            //jsString.Append(", { effect: \"horizontal\" }");
            jsString.Append("); ");
            jsString.Append("}); ");

            litJSOutput.Text = String.Format("<script type=\"text/javascript\">{0}</script>", jsString);
        }

        protected void RegisterJavascriptFileOnceInBody(string keyName, string pathToJsFile)
        {
            if (!Page.ClientScript.IsClientScriptIncludeRegistered(keyName))
            {
                Page.ClientScript.RegisterClientScriptInclude(keyName, pathToJsFile);
            }
        }

        private void GenerateDOM()
        {
            string defaultTemplate = string.Format("{0}{1}", Tokens.Tabs, Tokens.Panes);

            var template = new Template();
            template.LoadByPrimaryKey(_templateId.GetValueOrDefault(-1));

            litOutput.Text = Tokenize(template.Body ?? defaultTemplate);
        }

        private string GeneratePanes()
        {
            int TabNumber = 1;

            var output = new StringBuilder();

            output.Append(String.Format("<div id='Tabs_{0}_panes' class='panes'>", ModuleId));

            foreach (Pane pane in GetAllModulePanes())
            {
                output.Append(String.Format("<div class='pane Tabs_{0}_pane' title='{1}' style='display:none;'>{2}</div>", ModuleId, pane.Title, pane.Body));

                TabNumber++;
            }

            output.Append("</div>");

            return output.ToString();
        }

        private string GenerateTabs()
        {
            int TabNumber = 1;

            var output = new StringBuilder();

            output.Append(String.Format("<ul id='Tabs_{0}_tabs' class='tabs'>", ModuleId));

            foreach (Pane pane in GetAllModulePanes())
            {
                output.Append(String.Format("<li id='Tabs_{0}_tab_{2}' class='tab {1}'><a id='tab-{0}-{2}' href='#tab-{0}-{2}'><span>{3}</span></a></li>", ModuleId, _style, TabNumber, pane.Title));

                TabNumber++;
            }

            output.Append("</ul>");

            return output.ToString();
        }

        private IEnumerable<Pane> GetAllModulePanes()
        {
            var q = new PaneQuery();
            q.Where(q.PortalID == PortalId && q.ModuleID == ModuleId && q.IsVisible == true);
            q.OrderBy(q.DisplayOrder.Ascending);

            var slides = new PaneCollection();
            slides.Load(q);

            return slides;
        }

        private void IncludeJS()
        {
            if (string.IsNullOrEmpty(HostSettings.GetHostSetting(ModuleSettingNames.NoJQuery)) && (HttpContext.Current.Items["jquery_registered"] == null && HttpContext.Current.Items["jQuery"] == null))
            {
                //RegisterJavascript(String.Format("{0}{1}js/jquery-1.3.1.min.js", Globals.ApplicationPath, ModuleWebPath));
                //HttpContext.Current.Items.Add("jquery_registered", "true");
            }
            var tabsScript = String.Format("{0}{1}js/jquery.tabs.min.js", Globals.ApplicationPath, ModuleWebPath);
            RegisterJavascriptFileOnceInBody(tabsScript, tabsScript);

            //RegisterJavascript(String.Format("{0}{1}js/jquery.tabs.min.js", Globals.ApplicationPath, ModuleWebPath));

        }

        private void LoadVariables()
        {
            if (Settings[ModuleSettingNames.TemplateId] != null)
                _templateId = Convert.ToInt32(Settings[ModuleSettingNames.TemplateId]);

            _style = Settings[ModuleSettingNames.Style] != null ? Convert.ToString(Settings[ModuleSettingNames.Style]) : "blue";
        }

        private string Tokenize(string template)
        {
            var output = new StringBuilder();
            MatchCollection templateArray = Regex.Matches(template, @"\[.*?\]|[^\[.*?\]]+|[\.|\?]+");

            for (int i = 0; i < templateArray.Count; i++)
            {
                // We're using this type of loop rather than a foreach loop so we
                // can implement code blocks e.g. [HASTabS] lipsum [/HASTabS].
                switch (templateArray[i].Value)
                {
                    case Tokens.Tabs:
                        output.Append(GenerateTabs());
                        break;
                    case Tokens.Panes:
                        output.Append(GeneratePanes());
                        break;
                    default:
                        output.Append(templateArray[i]);
                        break;
                }
            }

            return output.ToString();
        }

        #endregion
    }

    public static class Tokens
    {
        public const string Tabs = "[TABS]";
        public const string Panes = "[PANES]";
    }


}